Use a single profile set per workspace
authorAleksey Kladov <aleksey.kladov@gmail.com>
Wed, 2 Nov 2016 15:16:44 +0000 (18:16 +0300)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Thu, 3 Nov 2016 11:13:22 +0000 (14:13 +0300)
src/cargo/core/manifest.rs
src/cargo/core/workspace.rs
src/cargo/ops/cargo_clean.rs
src/cargo/ops/cargo_compile.rs
src/cargo/util/toml.rs
tests/profiles.rs

index c26876fc2ec9cd2fdcd915b140ad5c732a3bd67e..4e693ff2b3f24a946c19df9db4d678c8c3b012f9 100644 (file)
@@ -33,6 +33,7 @@ pub struct Manifest {
 pub struct VirtualManifest {
     replace: Vec<(PackageIdSpec, Dependency)>,
     workspace: WorkspaceConfig,
+    profiles: Profiles,
 }
 
 /// General metadata about a package which is just blindly uploaded to the
@@ -139,7 +140,7 @@ pub struct Profile {
     pub panic: Option<String>,
 }
 
-#[derive(Default, Clone, Debug)]
+#[derive(Default, Clone, Debug, PartialEq, Eq)]
 pub struct Profiles {
     pub release: Profile,
     pub dev: Profile,
@@ -250,10 +251,12 @@ impl Manifest {
 
 impl VirtualManifest {
     pub fn new(replace: Vec<(PackageIdSpec, Dependency)>,
-               workspace: WorkspaceConfig) -> VirtualManifest {
+               workspace: WorkspaceConfig,
+               profiles: Profiles) -> VirtualManifest {
         VirtualManifest {
             replace: replace,
             workspace: workspace,
+            profiles: profiles,
         }
     }
 
@@ -264,6 +267,10 @@ impl VirtualManifest {
     pub fn workspace_config(&self) -> &WorkspaceConfig {
         &self.workspace
     }
+
+    pub fn profiles(&self) -> &Profiles {
+        &self.profiles
+    }
 }
 
 impl Target {
index afa6e3bf2b101f4a2148961306b9bb84b71780b9..65f1537647c7d535c507c8dbd2f8a5017fd955d5 100644 (file)
@@ -4,7 +4,7 @@ use std::path::{Path, PathBuf};
 use std::slice;
 
 use core::{Package, VirtualManifest, EitherManifest, SourceId};
-use core::{PackageIdSpec, Dependency};
+use core::{PackageIdSpec, Dependency, Profile, Profiles};
 use ops;
 use util::{Config, CargoResult, Filesystem, human};
 use util::paths;
@@ -162,6 +162,14 @@ impl<'cfg> Workspace<'cfg> {
         self.config
     }
 
+    pub fn profiles(&self) -> &Profiles {
+        let root = self.root_manifest.as_ref().unwrap_or(&self.current_manifest);
+        match *self.packages.get(root) {
+            MaybePackage::Package(ref p) => p.manifest().profiles(),
+            MaybePackage::Virtual(ref m) => m.profiles(),
+        }
+    }
+
     /// Returns the root path of this workspace.
     ///
     /// That is, this returns the path of the directory containing the
@@ -432,6 +440,33 @@ impl<'cfg> Workspace<'cfg> {
                   extra);
         }
 
+        if let Some(ref root_manifest) = self.root_manifest {
+            let default_profiles = Profiles {
+                release: Profile::default_release(),
+                dev: Profile::default_dev(),
+                test: Profile::default_test(),
+                test_deps: Profile::default_dev(),
+                bench: Profile::default_bench(),
+                bench_deps: Profile::default_release(),
+                doc: Profile::default_doc(),
+                custom_build: Profile::default_custom_build(),
+            };
+
+            for pkg in self.members().filter(|p| p.manifest_path() != root_manifest) {
+                if pkg.manifest().profiles() != &default_profiles {
+                    let message = &format!("profiles for the non root package will be ignored, \
+                                            specify profiles at the workspace root:\n\
+                                            package:   {}\n\
+                                            workspace: {}",
+                                           pkg.manifest_path().display(),
+                                           root_manifest.display());
+
+                    //TODO: remove `Eq` bound from `Profiles` when the warning is removed.
+                    try!(self.config.shell().warn(&message));
+                }
+            }
+        }
+
         Ok(())
     }
 }
index e19b37f116fc20ecd09930d532adc9b6382c15e5..6d544c19be24fc980662892d423094f8117ee7a9 100644 (file)
@@ -32,7 +32,7 @@ pub fn clean(ws: &Workspace, opts: &CleanOptions) -> CargoResult<()> {
     let resolve = try!(ops::resolve_ws(&mut registry, ws));
     let packages = ops::get_resolved_packages(&resolve, registry);
 
-    let profiles = try!(ws.current()).manifest().profiles();
+    let profiles = ws.profiles();
     let host_triple = try!(opts.config.rustc()).host.clone();
     let mut cx = try!(Context::new(ws, &resolve, &packages, opts.config,
                                    BuildConfig {
index 5a9513f94ccb38a2842e4877be6cc0910a76085f..3dc8cd916d4c75ee7c2df8f749d73b258a732d13 100644 (file)
@@ -169,7 +169,7 @@ pub fn compile_ws<'a>(ws: &Workspace<'a>,
         bail!("jobs must be at least 1")
     }
 
-    let profiles = root_package.manifest().profiles();
+    let profiles = ws.profiles();
     if spec.len() == 0 {
         try!(generate_targets(root_package, profiles, mode, filter, release));
     }
index 4686eb9a29dcdc4116f29d6182ee1480bc74c1a7..6a77c32bdc47515815145718fb59129a358ba6e6 100644 (file)
@@ -725,6 +725,7 @@ impl TomlManifest {
             platform: None,
             layout: layout,
         }));
+        let profiles = build_profiles(&self.profile);
         let workspace_config = match self.workspace {
             Some(ref config) => {
                 WorkspaceConfig::Root { members: config.members.clone() }
@@ -733,7 +734,7 @@ impl TomlManifest {
                 bail!("virtual manifests must be configured with [workspace]");
             }
         };
-        Ok((VirtualManifest::new(replace, workspace_config), nested_paths))
+        Ok((VirtualManifest::new(replace, workspace_config, profiles), nested_paths))
     }
 
     fn replace(&self, cx: &mut Context)
index ab060bba265ece822cb60408467a59ec77a15a17..00169adaa3f0edbaf7c3deaff6b71000ad6e58d2 100644 (file)
@@ -187,3 +187,71 @@ fn top_level_overrides_deps() {
                     prefix = env::consts::DLL_PREFIX,
                     suffix = env::consts::DLL_SUFFIX)));
 }
+
+#[test]
+fn profile_in_non_root_manifest_triggers_a_warning() {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [project]
+            name = "foo"
+            version = "0.1.0"
+            authors = []
+
+            [workspace]
+            members = ["bar"]
+
+            [profile.dev]
+            debug = false
+        "#)
+        .file("src/main.rs", "fn main() {}")
+        .file("bar/Cargo.toml", r#"
+            [project]
+            name = "bar"
+            version = "0.1.0"
+            authors = []
+            workspace = ".."
+
+            [profile.dev]
+            opt-level = 1
+        "#)
+        .file("bar/src/main.rs", "fn main() {}");
+    p.build();
+
+    assert_that(p.cargo_process("build").cwd(p.root().join("bar")).arg("-v"),
+                execs().with_status(0).with_stderr("\
+[WARNING] profiles for the non root package will be ignored, specify profiles at the workspace root:
+package:   [..]
+workspace: [..]
+[COMPILING] bar v0.1.0 ([..])
+[RUNNING] `rustc [..]`
+[FINISHED] debug [unoptimized] target(s) in [..]"));
+}
+
+#[test]
+fn profile_in_virtual_manifest_works() {
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [workspace]
+            members = ["bar"]
+
+            [profile.dev]
+            opt-level = 1
+            debug = false
+        "#)
+        .file("src/main.rs", "fn main() {}")
+        .file("bar/Cargo.toml", r#"
+            [project]
+            name = "bar"
+            version = "0.1.0"
+            authors = []
+            workspace = ".."
+        "#)
+        .file("bar/src/main.rs", "fn main() {}");
+    p.build();
+
+    assert_that(p.cargo_process("build").cwd(p.root().join("bar")).arg("-v"),
+                execs().with_status(0).with_stderr("\
+[COMPILING] bar v0.1.0 ([..])
+[RUNNING] `rustc [..]`
+[FINISHED] debug [optimized] target(s) in [..]"));
+}